/*
 * NIST Healthcare Test Framework
 * TestAgent.java May 21, 2009
 *
 * This code was produced by the National Institute of Standards and
 * Technology (NIST). See the "nist.disclaimer" file given in the distribution
 * for information on the use and redistribution of this software.
 */
package gov.nist.healthcare.testframework.application;

import gov.nist.healthcare.configuration.testframework.testagent.TestAgentConfigurationDocument.TestAgentConfiguration.SpecificConfiguration;
import gov.nist.healthcare.core.message.HL7Message;
import gov.nist.healthcare.core.message.Name;
import gov.nist.healthcare.core.message.v2.HL7V2Message;
import gov.nist.healthcare.core.message.v2.HL7V2Name;
import gov.nist.healthcare.core.message.v3.HL7V3Message;
import gov.nist.healthcare.core.message.v3.HL7V3Name;
import gov.nist.healthcare.testframework.Actor;
import gov.nist.healthcare.testframework.Environment;
import gov.nist.healthcare.testframework.communication.client.ClientThread;
import gov.nist.healthcare.testframework.communication.mllp.client.MLLPClient;
import gov.nist.healthcare.testframework.communication.soap.client.SoapClient;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;

/**
 * This abstract class defines a Test Agent.
 * 
 * @author Sydney Henrard (NIST)
 */
public abstract class TestAgent {

    private static final Logger logger = Logger.getLogger(TestAgent.class.getName());

    protected Name name = null;

    public Name getName() {
        return name;
    }

    public void setName(Name name) {
        this.name = name;
    }

    /**
     * This method is called after the test agent has been created.
     * 
     * @param params
     * @return true if everything went fine; false otherwise
     */
    public boolean init(Map<String, String> params) {
        return true;
    }

    /**
     * This method is called when the test framework receives a message for this
     * test agent.
     * 
     * @param message
     * @return a list of message to send back
     */
    public abstract List<HL7Message> newMessage(HL7Message message);

    /**
     * This method provides a way to generate messages that are based on the
     * incoming message. By default it sends an empty List of HL7Messages
     * 
     * @param message
     *        the incoming message the incoming message
     * @return a list of generated message
     */
    public List<HL7Message> getNextMessageList(HL7Message message) {
        /*
         * By default this method returns an empty list but test Agents can
         * override it
         */
        ArrayList<HL7Message> result = new ArrayList<HL7Message>();
        return result;
    }

    /**
     * Load the data contained in the <SpecificConfiguration> section
     * 
     * @param specificConfiguration
     * @return true if everything went fine ; false otherwise
     */
    public boolean loadSpecificConfiguration(
            SpecificConfiguration specificConfiguration) {
        return true;
    }

    public abstract boolean checkBeforeSending(HL7Message message);

    /**
     * This method is called by the test engine to check if the message can be
     * sent.
     * 
     * @param trigger
     *        A String representing a condition to check if the message can be
     *        sent.
     * @return true if the message can be sent; false otherwise
     */
    public boolean canSend(String trigger) {
        return true;
    }

    /**
     * This method is called to get the next message to send depending on other
     * messages.
     * 
     * @param messages
     *        a list of messages
     * @return the next message to send; null otherwise
     */
    public HL7Message getNextMessage(Map<String, HL7Message> messages) {
        return null;
    }

    public void send(HL7Message message, boolean secure) {
        if (checkBeforeSending(message)) {
            Name sending = message.getSending();
            Name receiving = message.getReceiving();
            Actor actor = Environment.getInstance().getActor(receiving, sending);
            if (actor == null) {
                // TODO: See when the actor is not in the config file.
            }
            // Get an instance of ClientThread depending on the message to sent
            ClientThread client = null;
            if (actor.getName() instanceof HL7V2Name) {
                if (message instanceof HL7V2Message) {
                    client = new MLLPClient(secure, message.getEncoding());
                }
            } else if (actor.getName() instanceof HL7V3Name) {
                if (message instanceof HL7V3Message) {
                    client = new SoapClient(secure);
                }
            }
            if (client != null) {
                client.setActor(actor);
                client.setMessage(message);
                client.start();
            }
        } else {
            logger.error(name.toString()
                    + " is trying to send inappropriate message");
            logger.error(message.getMessageAsString());
        }
    }

}
